package utils;

import java.util.*;

/**
 * Utility class responsible for calculations involving date
 * @author Meera, Shayan
 */
public class DateUtils {

    private static long MILLI_SEC_DAY = 86400000L;

    public static Date getStartOfDay(Date day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date getEndOfDay(Date day) {
        Date tomorrow = new Date(day.getTime() + MILLI_SEC_DAY);
        return getStartOfDay(tomorrow);
    }

    public static Date stringToDate(String s) {
        Calendar c = Calendar.getInstance();

        c.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(0, 2)));
        c.set(Calendar.MONTH, Integer.parseInt(s.substring(3, 5)) - 1);
        c.set(Calendar.YEAR, Integer.parseInt(s.substring(6, 10)));
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static String DatetoString(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);

        String strDD = Integer.toString(c.get(Calendar.DAY_OF_MONTH));
        if (strDD.length() == 1) {
            strDD = "0" + strDD;
        }
        String strMM = Integer.toString(c.get(Calendar.MONTH) + 1);
        if (strMM.length() == 1) {
            strMM = "0" + strMM;
        }
        String strYYYY = Integer.toString(c.get(Calendar.YEAR));
        String strDate = strDD + "/" + strMM + "/" + strYYYY;

        return strDate;
    }

    public static String DateToSOAP(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);

        String strDD = Integer.toString(c.get(Calendar.DAY_OF_MONTH));
        if (strDD.length() == 1) {
            strDD = "0" + strDD;
        }
        String strMM = Integer.toString(c.get(Calendar.MONTH) + 1);
        if (strMM.length() == 1) {
            strMM = "0" + strMM;
        }

        String strYYYY = Integer.toString(c.get(Calendar.YEAR));
        String strHH = Integer.toString(c.get(Calendar.HOUR_OF_DAY));
        if (strHH.length() == 1) {
            strHH = "0" + strHH;
        }

        String strMin = Integer.toString(c.get(Calendar.MINUTE));
        if (strMin.length() == 1) {
            strMin = "0" + strMin;
        }

        String strSS = Integer.toString(c.get(Calendar.SECOND));
        if (strSS.length() == 1) {
            strSS = "0" + strSS;
        }

        // ISO 8601 format: CCYY-MM-DDThh:mm:ss
        String strDate = strYYYY + "-" + strMM + "-" + strDD + "T" + strHH + ":" + strMin + ":" + strSS;

        return strDate;
    }

    public static Date SOAPtoDate(String s) {
        // ISO 8601 format: CCYY-MM-DDThh:mm:ss
        if (s.equals("0001-01-01T00:00:00")) {
            return new Date(0L); // minimum possibel date
        }
        Calendar c = Calendar.getInstance();

        c.set(Calendar.YEAR, Integer.parseInt(s.substring(0, 4)));
        c.set(Calendar.MONTH, Integer.parseInt(s.substring(5, 7)) - 1);
        c.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(8, 10)));
        c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s.substring(11, 13)));
        c.set(Calendar.MINUTE, Integer.parseInt(s.substring(14, 16)));
        c.set(Calendar.SECOND, Integer.parseInt(s.substring(17)));

        return c.getTime();
    }

    public static Date getYesterday(Date day) {
        return new Date(day.getTime() - MILLI_SEC_DAY);
    }

    public static Date getNextDay(Date day) {
        // Add 1 day
        return new Date(day.getTime() + MILLI_SEC_DAY);
    }

    public static String[] getWeekDates(String year, String month) {
        int mthEnd = 31;
        int[] dayCnt = new int[10];


        String[] result = new String[10];
        Calendar startDate = Calendar.getInstance();
        Calendar endDate = Calendar.getInstance();

        startDate.set(Calendar.MONTH, Integer.parseInt(month) - 1);
        startDate.set(Calendar.YEAR, Integer.parseInt(year));
        endDate.set(Calendar.MONTH, Integer.parseInt(month) - 1);
        endDate.set(Calendar.YEAR, Integer.parseInt(year));


        switch (Integer.parseInt(month) - 1) {
            case 0:
            case 2:
            case 4:
            case 6:
            case 7:
            case 9:
            case 11:
                mthEnd = 31;
                break;
            case 3:
            case 5:
            case 8:
            case 10:
                mthEnd = 30;
                break;
            case 1:
                if ((Integer.parseInt(year)) % 4 == 0) {
                    mthEnd = 29;
                } else {
                    mthEnd = 28;
                }
                break;
        }



        startDate.set(Calendar.DAY_OF_MONTH, 1);

        int dayOfWk = startDate.get(Calendar.DAY_OF_WEEK);

        dayCnt[0] = 1;
        dayCnt[1] = 7 - dayOfWk + 1;
        dayCnt[2] = dayCnt[1] + 1;
        dayCnt[3] = dayCnt[2] + 6;
        dayCnt[4] = dayCnt[3] + 1;
        dayCnt[5] = dayCnt[4] + 6;
        dayCnt[6] = dayCnt[5] + 1;
        if (mthEnd <= (dayCnt[6] + 6)) {
            dayCnt[7] = mthEnd;
        } else {
            dayCnt[7] = dayCnt[6] + 6;
        }
        if ((mthEnd < (dayCnt[7] + 1)) && (dayCnt[7] != mthEnd)) {
            dayCnt[8] = mthEnd;
        } else {
            dayCnt[8] = dayCnt[7] + 1;
        }
        if (mthEnd <= (dayCnt[8] + 6)) {
            dayCnt[9] = mthEnd;
        } else {
            dayCnt[9] = dayCnt[8] + 6;
        }

        for (int i = 0; i < 10; i++) {

            endDate.set(Calendar.DAY_OF_MONTH, dayCnt[i]);
            result[i] = DateUtils.DatetoString(endDate.getTime());
        }
        return result;
    }

    public static String getDaysOfWk(int wkDay, int wk, String mth, String year) {

        int i = 0;

        String result = new String();
        //Get the start and end dates of all the weeks in the given month and year
        String[] daysOfMth = getWeekDates(year, mth);

        //Finding and assigining the start and end dates of the week given the week of the month
        if (wk == 1) {
            i = 0;
        }
        if (wk == 2) {
            i = 2;
        }
        if (wk == 3) {
            i = 4;
        }
        if (wk == 4) {
            i = 6;
        }
        if (wk == 5) {
            i = 8;
        }

        //Calculating the date given day of week,month and year
        for (int j = Integer.parseInt(daysOfMth[i].substring(0,
                2)); j <= Integer.parseInt(daysOfMth[i + 1].substring(0, 2)); j++) {

            Calendar calrpt = Calendar.getInstance();
            calrpt.set(Calendar.DAY_OF_MONTH, j);
            calrpt.set(Calendar.MONTH, (Integer.parseInt(mth) - 1));
            calrpt.set(Calendar.YEAR, Integer.parseInt(year));

            int dayOfWk = calrpt.get(Calendar.DAY_OF_WEEK);
            if (((dayOfWk) - 1) == (wkDay)) {

                result = DatetoString(calrpt.getTime());
            }
        }

        return result;

    }
}
